#pragma once

#include <string>
#include <chrono>
#include <iomanip>
#include <sstream>

// Utilities
#include "UtCallbackHolder.hpp"
#include "json/json.h"

class WsfPlatform;
class WsfSensor;
class WsfTrack;
class WsfMover;
class WsfSimulation;
class WsfMessage;
class WsfTask;
class WsfTrackId;
class WsfZone;
class WsfAdvancedBehaviorTreeNode;
class WsfAdvancedBehaviorTree;
class WsfBehaviorTreeNode;
class WsfBehaviorTree;
class WsfFuelingOperation;
class WsfFuel;
class WsfImage;
class WsfProcessor;
class WsfScriptStateMachine;
class WsfSensorMode;
class WsfSensorResult;
class WsfVisualPart;
class WsfLocalTrack;
class WsfCallback;
class WsfWeaponEngagement;
class WsfEM_Xmtr;
class WsfGuidanceComputer;
class WsfImplicitWeapon;
class WsfWeapon;
class WsfWeaponMode;
class WsfQuantumTaskerProcessor;
class WsfEM_Rcvr;
class WsfEM_Interaction;
class WsfDirectedEnergyWeapon;
class GenUDP_Connection;

class ObserverEventInterface
{
public:
  ObserverEventInterface(UtCallbackHolder &callBackes, GenUDP_Connection *conn);
  ~ObserverEventInterface() {};
  void initCallBack(UtCallbackHolder &callBackes);

  void SendPacket(const std::string &aMessage);

  // WsfMoverObserver
  void MoverUpdated(double aSimTime, WsfMover *aMover);

  // WsfPlatformObserver
  void PlatformAdded(double aSimTime, WsfPlatform *aPlatform);
  void PlatformDeleted(double aSimTime, WsfPlatform *aPlatform);

  // WsfSensorObserver
  void SensorScanUpdated(double aSimTime, WsfSensor *aSensor);

  // WsfSimulationObserver
  void RequestTimeAdvance(double aSimTime, double aRequestedTime, double aGrantedTime);
  void SimulationClockRateChange(double aSimTime);
  void SimulationInitializing();
  void SimulationStarting();
  void SimulationPausing();
  void SimulationResuming();
  void SimulationComplete(double aSimTime);

  // WsfTrackObserver
  void LocalTrackDropped(double aSimTime, WsfPlatform *aPlatform, const WsfLocalTrack *aTrack);
  void LocalTrackInitiated(double aSimTime, WsfPlatform *aPlatform, const WsfLocalTrack *aLocalTrack, const WsfTrack *aSensorTrack);
  void LocalTrackUpdated(double aSimTime, WsfPlatform *aPlatform, const WsfLocalTrack *aLocalTrack, const WsfTrack *aSensorTrack);
  void SensorTrackCoasted(double aSimTime, WsfSensor *aSensor, const WsfTrack *aTrack);
  void SensorTrackDropped(double aSimTime, WsfSensor *aSensor, const WsfTrack *aTrack);
  void SensorTrackInitiated(double aSimTime, WsfSensor *aSensor, const WsfTrack *aTrack);
  void SensorTrackUpdated(double aSimTime, WsfSensor *aSensor, const WsfTrack *aTrack);

  // WsfWeaponObserve
  void WeaponFireAborted(double aSimTime, WsfWeapon *aWeapon, const WsfTrack *aTrack, double aTime);
  void WeaponFired(double aSimTime, const WsfWeaponEngagement *aEngagement, const WsfTrack *aTrack);
  void WeaponFireRequested(double aSimTime, WsfWeapon *aWeapon, const WsfTrack *aTrack, double aTime);
  void WeaponPlatformPendingAdd(double aSimTime, WsfPlatform *aPlatform, const WsfWeaponEngagement *aEngagement, const WsfTrack *aTrack);
  void WeaponHit(double aSimTime, const WsfWeaponEngagement *aEngagement, WsfPlatform *aTarget);
  void WeaponKilled(double aSimTime, WsfWeapon *aWeapon);
  void WeaponMissed(double aSimTime, const WsfWeaponEngagement *aEngagement, WsfPlatform *aTarget);

private:
  GenUDP_Connection *mConnectionPtr = nullptr;
};
